home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / AX25USER.C < prev    next >
C/C++ Source or Header  |  1989-09-25  |  6KB  |  260 lines

  1. /* User subroutines for AX.25 */
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "timer.h"
  5. #include "iface.h"
  6. #include "ax25.h"
  7. #include "lapb.h"
  8. #include <ctype.h>
  9.  
  10. /* Open an AX.25 connection */
  11. struct ax25_cb *
  12. open_ax25(addr,window,r_upcall,t_upcall,s_upcall,iface,user)
  13. struct ax25 *addr;        /* Addresses */
  14. int16 window;            /* Window size in bytes */
  15. void (*r_upcall)();        /* Receiver upcall handler */
  16. void (*t_upcall)();        /* Transmitter upcall handler */
  17. void (*s_upcall)();        /* State-change upcall handler */
  18. struct interface *iface;    /* Hardware interface structure */
  19. char *user;            /* User linkage area */
  20. {
  21.     register struct ax25_cb *axp;
  22.     struct ax25_call *axc;
  23.     struct ax25_cb *cr_ax25();
  24.     void lapbstate();
  25.  
  26.     if((axc = find_axcall(ax25_excl,&addr->dest)) != NULLAXCALL &&
  27.         ((axc->flags & MULTI_IF) || axc->interface == iface))
  28.         return NULLAX25;
  29.     if((axp = cr_ax25(&addr->dest,&addr->source)) == NULLAX25)
  30.         return NULLAX25;
  31.     ASSIGN(axp->addr,*addr);
  32.     if(addr->ndigis != 0){
  33.         axp->t1.start *= (addr->ndigis + 1);
  34.         axp->t2.start *= (addr->ndigis + 1);
  35.         /*axp->t3.start *= (addr->ndigis + 1);
  36.         axp->t4.start *= (addr->ndigis + 1);*/
  37.     }
  38.     axp->window = window;
  39.     axp->r_upcall = r_upcall;
  40.     axp->t_upcall = t_upcall;
  41.     axp->s_upcall = s_upcall;
  42.     axp->interface = iface;
  43.     axp->user = user;
  44.  
  45.     if (axp->state == DISCONNECTED){
  46.         /* Don't send anything if the connection already exists */
  47.         lapbstate(axp,SETUP,LAPBNOMS);
  48.         sendctl(axp,COMMAND,SABM|PF);
  49.     }
  50.     return axp;
  51. }
  52.  
  53. /* Send data on an AX.25 connection. Caller must provide PID */
  54. int
  55. send_ax25(axp,bp)
  56. struct ax25_cb *axp;
  57. struct mbuf *bp;
  58. {
  59.     if(axp == NULLAX25 || bp == NULLBUF || axp->fin){
  60.         free_p(bp);
  61.         return -1;
  62.     }
  63.     enqueue(&axp->txq,bp);
  64.     return lapb_output(axp);
  65. }
  66.  
  67. /* Send data on an AX.25 connection, creating packets sized "paclen" */
  68. sendp_ax25(axp,bp,pid)
  69. register struct ax25_cb *axp;
  70. struct mbuf *bp;
  71. char pid;
  72. {
  73.     register struct mbuf *tbp;
  74.     int16 bsize;
  75.  
  76.     if(axp == NULLAX25 || bp == NULLBUF)
  77.         return;
  78.     bsize = len_mbuf(bp);
  79.     while(bsize != 0){
  80.         if (bsize <= axp->paclen) {
  81.             if((tbp = pushdown(bp,1)) == NULLBUF) {/* make space for PID */
  82.                 free_p(bp);
  83.                 break;        /* out of memory! */
  84.             }
  85.             bsize = 0;
  86.         } else {
  87.             /* Allocate buffer, allowing space for PID */
  88.             if((tbp = alloc_mbuf(axp->paclen + 1)) == NULLBUF) {
  89.                 free_p(bp);
  90.                 break;        /* out of memory! */
  91.             }
  92.             tbp->cnt = 1 + pullup(&bp,tbp->data + 1,axp->paclen);
  93.             bsize -= axp->paclen;
  94.         }
  95.         *tbp->data = pid;
  96.         send_ax25(axp,tbp);
  97.     }
  98. }
  99.  
  100. /* Send UI frames to an AX.25-type iface, creating packets sized "paclen" */
  101. sendui_ax25(ifp,addr,bp,pid)
  102. struct interface *ifp;
  103. struct ax25 *addr;
  104. struct mbuf *bp;
  105. char pid;
  106. {
  107.     register struct mbuf *tbp;
  108.     int16 bsize;
  109.     extern int16 paclen;
  110.  
  111.     if(ifp == NULLIF || bp == NULLBUF)
  112.         return;
  113.     bsize = len_mbuf(bp);
  114.     while(bsize != 0){
  115.         if (bsize <= paclen) {
  116.             if((tbp = pushdown(bp,1)) == NULLBUF) {/* make space for PID */
  117.                 free_p(bp);
  118.                 break;        /* out of memory! */
  119.             }
  120.             bsize = 0;
  121.         } else {
  122.             /* Allocate buffer, allowing space for PID */
  123.             if((tbp = alloc_mbuf(paclen + 1)) == NULLBUF) {
  124.                 free_p(bp);
  125.                 break;        /* out of memory! */
  126.             }
  127.             tbp->cnt = 1 + pullup(&bp,tbp->data + 1,paclen);
  128.             bsize -= paclen;
  129.         }
  130.         *tbp->data = pid;
  131.         senduiframe(ifp,addr,tbp);
  132.     }
  133. }
  134.  
  135. /* Receive incoming data on an AX.25 connection */
  136. struct mbuf *
  137. recv_ax25(axp,cnt)
  138. register struct ax25_cb *axp;
  139. int16 cnt;
  140. {
  141.     struct mbuf *bp;
  142.     unsigned rxqlen;
  143.  
  144.     if(axp->rxq == NULLBUF)
  145.         return NULLBUF;
  146.  
  147.     if ((rxqlen = len_mbuf(axp->rxq)) <= cnt || cnt == 0){
  148.         bp = axp->rxq;
  149.         axp->rxq = NULLBUF;
  150.         cnt = rxqlen;
  151.     } else {
  152.         if ((bp = alloc_mbuf(cnt)) == NULLBUF)
  153.             return NULLBUF;
  154.  
  155.         cnt = bp->cnt = pullup(&axp->rxq,bp->data,cnt);
  156.     }
  157.     /* If this has un-busied us, send a RR to reopen the window */
  158.     if(rxqlen >= axp->window && (rxqlen - cnt) < axp->window)
  159.         sendctl(axp,RESPONSE,RR);
  160.     return bp;
  161. }
  162.  
  163. /* Get a line of text from an AX.25 connection (up to \r) */
  164. /* The textline may span multiple incoming packets, so NULLBUF is returned */
  165. /* as long as the line is incomplete (and it is saved) */
  166. struct mbuf *
  167. recvl_ax25(axp,cnt)
  168. register struct ax25_cb *axp;
  169. int16 cnt;
  170. {
  171.     struct mbuf *bp;
  172.     unsigned rxqlen;
  173.  
  174.     if(axp->rxq == NULLBUF)
  175.         return NULLBUF;
  176.  
  177.     rxqlen = len_mbuf(axp->rxq);
  178.  
  179.     if ((bp = pullline(&axp->rxq,cnt)) != NULLBUF){
  180.         /* If this has un-busied us, send a RR to reopen the window */
  181.         if(rxqlen >= axp->window && (rxqlen - bp->cnt) < axp->window)
  182.             sendctl(axp,RESPONSE,RR);
  183.     }
  184.     return bp;
  185. }
  186.  
  187. /* "Gracefully Close" an AX.25 connection */
  188. close_ax25(axp)
  189. struct ax25_cb *axp;
  190. {
  191.     axp->fin = YES;            /* set FIN flag */
  192.     if (axp->txq == NULLBUF &&    /* no outstanding frames? */
  193.         axp->state != DISCPENDING)    /* not already disconnecting? */
  194.         disc_ax25(axp);        /* start disconnecting now */
  195. }
  196.  
  197. /* Close an AX.25 connection */
  198. disc_ax25(axp)
  199. struct ax25_cb *axp;
  200. {
  201.     void lapbstate();
  202.  
  203.     switch (axp->state)
  204.     {
  205.     case DISCONNECTED:
  206.         break;            /* Ignored */
  207.     case DISCPENDING:        /* was pending, just drop it */
  208.         lapbstate(axp,DISCONNECTED,LAPBDISC);
  209.         del_ax25(axp);
  210.         break;
  211.     case CONNECTED:            /* was connected, full retries */
  212.         lapbstate(axp,DISCPENDING,LAPBNOMS);
  213.         sendctl(axp,COMMAND,DISC|PF);
  214.         break;
  215.     default:            /* SETUP */
  216.         lapbstate(axp,DISCPENDING,LAPBNOMS);
  217.         axp->retries = axp->n2 - 2; /* try 3 times only */
  218.         sendctl(axp,COMMAND,DISC|PF);
  219.         break;
  220.     }
  221. }
  222.  
  223. /* Verify that axp points to a valid ax25 control block */
  224. ax25val(axp)
  225. struct ax25_cb *axp;
  226. {
  227.     register struct ax25_cb *axp1;
  228.     register int i;
  229.  
  230.     if(axp == NULLAX25)
  231.         return 0;    /* Null pointer can't be valid */
  232.     for(i=0; i < NHASH; i++)
  233.         for(axp1 = ax25_cb[i];axp1 != NULLAX25; axp1 = axp1->next)
  234.             if(axp1 == axp)
  235.                 return 1;
  236.     return 0;
  237. }
  238.  
  239. /* Force a retransmission */
  240. kick_ax25(axp)
  241. struct ax25_cb *axp;
  242. {
  243.     void recover();
  244.  
  245.     if(!ax25val(axp))
  246.         return -1;
  247.     recover((int *)axp);
  248.     return 0;
  249. }
  250.  
  251. /* Abruptly terminate an AX.25 connection */
  252. reset_ax25(axp)
  253. struct ax25_cb *axp;
  254. {
  255.     void lapbstate();
  256.  
  257.     lapbstate(axp,DISCONNECTED,LAPBNOMS);
  258.     del_ax25(axp);
  259. }
  260.